﻿
using ActionSystem.Core.Utils;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using XMLib;

namespace ActionSystem.Core
{
    [System.Serializable]
    public class BaseState:IShadowCopy
    {
        #region Runtime
        #region 配置数据
        [NonSerialized]
        public const int UNKNOWN_UID = -1;
        [DisableEdit]
        [CustomLabel("状态ID")]
        [Drawable]
        [SerializeField]
        private int uid = UNKNOWN_UID;
#if UNITY_EDITOR
        [CustomLabel("帧数")]
        [DisableEdit]
        [Drawable]
        private int _frameCount = 0;
#endif
        [CustomLabel("能否循环")]
        [SerializeField]
        [Drawable(true)]
        private bool _enableLoop = false;
        [CustomLabel("状态名称")]
        [SerializeField]
        [Drawable]
        private string _stateName = "New State";
        [SerializeField]
        [Drawable(false)]
        private List<BaseStateActionConfig> _actionDatas = new List<BaseStateActionConfig>();        
        [Drawable(false)]
        [SerializeField]        
        private List<FrameConfig> _frames = new List<FrameConfig>();
        #endregion
        #region IShadowCopy
        /// <summary>
        /// 重置不能共享的引用
        /// 子类需要覆写，子类不希望共享的字段
        /// </summary>
        public virtual void ResetUnSharedFileds()
        {
            _actions = new List<BaseStateAction>();
        }
        /// <summary>
        /// 浅拷贝，配合ResetUnSharedFileds使用
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return MemberwiseClone();
        }
        #endregion
        #region 内部数据
        BaseStateMachine stateMachine;
        [JsonIgnore]
        public BaseStateMachine StateMachine=>stateMachine;
        void SetStateMachine(BaseStateMachine stateMachine)
        {
            this.stateMachine = stateMachine;
        }
        
        private int _frameIndex = -1;
                
        
        private bool _stateExposed = false;
        
        
        private int _loopCnt = -1;
        private float _weight = 1;
                
        public IEnumerable<BaseStateAction> GetActions()
        {
            if(StateExposed)
            {
                yield break;
            }
            foreach (var a in _actions)
            {
                yield return a;
            }
        }
        List<BaseStateAction> _actions = null;
        [JsonIgnore]
        public List<BaseStateActionConfig> ActionDatas => _actionDatas;
        [JsonIgnore]
        private List<BaseStateAction> Actions { get { if (_actions == null) _actions = new List<BaseStateAction>();return _actions; } }
        [JsonIgnore]
        public List<FrameConfig> Frames => _frames;
        #endregion
        #region 生命周期
        /// <summary>
        /// 更新状态的处于的帧数以及循环次数
        /// </summary>
        /// <param name="index"></param>
        /// <param name="loop"></param>
        public virtual void UpdateFrameIndexAndLoop()
        {
            if (!_stateExposed)
            {
                _frameIndex += 1;
                _frameIndex %= FrameCount;
                if(FrameIndex==0)
                {
                    LoopCnt += 1;                
                }            
                foreach (var action in Actions)
                {
                    action.UpdateIndexAndLoop(FrameIndex, LoopCnt);
                }
                foreach (var action in Actions)
                {
                    action.TryExit();
                }
                foreach (var action in Actions)
                {
                    action.TryEnter();
                }
                if (!EnableLoop && LoopCnt >= 1)
                {
                    _stateExposed = true;
                }
            }                       
            
        }
        public virtual void UpdateWeight(float weight)
        {
            Weight = weight;
        }
        /// <summary>
        /// State进入
        /// </summary>        
        public void Enter() 
        {                   
            if(_entered)
            {
                return;
            }
            //初始化操作
            SetActions(ActionDatas);
            _entered = true;            
            EnterState();
            //重置action
            foreach (var action in Actions)
            {
                action.Reset();
            }
            //action的OnStateEnter
            foreach (var action in Actions)
            {
                action.SetUpOnState();
            }
        }
        bool _entered = false;
        /// <summary>
        /// state退出
        /// </summary>
        public virtual void Exit() 
        {
            if (!_entered)
            {
                return;
            }
            _entered = false;    
            //action的OnStateExit
            foreach (var action in Actions)
            {
                action.RemoveFromState();
                //放回池子
                action.PoolItemDelete();
            }
            Actions.Clear();
            ExitState();
        }
        [JsonIgnore]
        public bool Entered => _entered;
        /// <summary>
        /// 初始化一些状态数据
        /// </summary>
        protected virtual void EnterState()
        {
#region 初始化帧数信息
            _frameIndex = -1;
            _loopCnt = -1;
            _stateExposed = false;
            _weight = 1;
#endregion
            
        }
        /// <summary>
        /// 状态退出
        /// </summary>
        protected virtual void ExitState()
        {

        }

        public void InheritingActions(BaseState currentState)
        {
            //从当状态继承action的状态
            foreach(var srcAction in currentState.Actions)
            {
                if(srcAction.IsExcuting)
                {
                    foreach(var destAction in Actions)
                    {
                        //类型相同，并且能够能够继承,且必须第一帧
                        if( destAction.Config.Begin == 0 &&
                            srcAction.Config.GetType() == destAction.Config.GetType() &&
                            srcAction.Config.canInherited &&
                            destAction.Config.canInheriting)
                        {                    
                            //克隆成功
                            if(destAction.SetNextStateActionData(srcAction.GetRawInnerData()))
                            {
                                srcAction.StopAction();
                                break;
                            }                                                        
                        }
                    }
                }
            }
        }
        #endregion
        #region 外部调用
        [JsonIgnore]
        public int UID
        {
            get => uid;
#if UNITY_EDITOR
            set
            {
                uid = value;
            }
#endif
        }
        [JsonIgnore]
        public string StateName
        {
            get => _stateName;
#if UNITY_EDITOR
            set
            {
                _stateName = value;
            }
#endif
        }
        [JsonIgnore]
        public bool EnableLoop => _enableLoop;
        [JsonIgnore]
        public int LoopCnt
        {
            get { return _loopCnt; }
            private set { _loopCnt = value; }
        }
        /// <summary>
        /// 是否状态持续时间大于本身逻辑时间
        /// </summary>
        [JsonIgnore]
        public bool StateExposed => _stateExposed;
        /// <summary>
        /// 当前处于的帧数
        /// </summary>
        [JsonIgnore]
        public int FrameIndex
        {
            get
            {
                return _frameIndex;
            }
        }
        /// <summary>
        /// 状态权重
        /// </summary>
        [JsonIgnore]
        public float Weight { get => _weight; protected set { value = Mathf.Clamp01(value); _weight = value; } }
     
        /// <summary>
        /// 整个状态的帧数，至少一帧
        /// </summary>
        [JsonIgnore]
        public int FrameCount
        {
            get => Frames.Count;
#if UNITY_EDITOR
            set
            {
                _frameCount = value;
            }
#endif
        }
        public virtual void OnStateInstance(BaseStateMachine stateMachine)
        {
            SetStateMachine(stateMachine);
        }
        void SetActions(List<BaseStateActionConfig> configs)
        {
            for(int i=0;i<configs.Count;i++)
            {
                var ac = GeneticPool<BaseStateAction>.Create();
                ac.SetUp(this, configs[i]);
                Actions.Add(ac);
            }
        }
        //当前帧的判定范围
        public FrameConfig GetBodyRangesFrame(int frameIndex)
        {
            if (_frames.Count == 0 || frameIndex < 0)
            {
                return null;
            }

            frameIndex %= _frames.Count;
            FrameConfig config = _frames[frameIndex];

            while (config.stayBodyRange)
            {
                --frameIndex;
                if (frameIndex < 0)
                {
                    return null;
                }
                config = _frames[frameIndex];
            }
            return config;
        }
        public bool IsStayBodyRanges(int frameIndex)
        {
            if (_frames.Count == 0 || frameIndex < 0)
            {
                return false;
            }
            frameIndex %= _frames.Count;
            FrameConfig config = _frames[frameIndex];
            return config.stayBodyRange;
        }
        public bool CurrentIsStayBodyRanges()
        {
            return IsStayBodyRanges(FrameIndex);
        }
        public List<RangeConfig> GetBodyRanges(int frameIndex)
        {
            return GetBodyRangesFrame(frameIndex)?.bodyRanges;
        }
        public List<RangeConfig> GetCurrentBodyRanges()
        {
            return GetBodyRanges(FrameIndex);
        }
        public FrameConfig GetAttackRangesFrame(int frameIndex)
        {
            if (_frames.Count == 0 || frameIndex < 0)
            {
                return null;
            }

            frameIndex %= _frames.Count;
            FrameConfig config = _frames[frameIndex];

            while (config.stayAttackRange)
            {
                --frameIndex;
                if (frameIndex < 0)
                {
                    return null;
                }
                config = _frames[frameIndex];
            }
            return config;
        }
        public bool IsStayAttackRanges(int frameIndex)
        {
            if (_frames.Count == 0 || frameIndex < 0)
            {
                return false;
            }
            frameIndex %= _frames.Count;
            FrameConfig config = _frames[frameIndex];
            return config.stayAttackRange;
        }
        public bool CurrentIsStayAttackRanges()
        {
            return IsStayAttackRanges(FrameIndex);
        }
        public List<RangeConfig> GetAttackRanges(int frameIndex)
        {
            return GetAttackRangesFrame(frameIndex)?.attackRanges;
        }
        public List<RangeConfig> GetCurrentAttackRanges()
        {
            return GetAttackRanges(FrameIndex);
        }
        #endregion
        #endregion
        #region Editor
        public void ResetUID()
        {
            uid = UNKNOWN_UID;
        }
        #endregion
    }

}
